package com.yanqu.xiuxian.gameserver.manger.elementalbonds;

import com.yanqu.xiuxian.config.backend.BusinessServerParamConfigParam;
import com.yanqu.xiuxian.config.elementalbonds.*;
import com.yanqu.xiuxian.config.elementalbonds.enums.ElementalBondsHonorMomentType;
import com.yanqu.xiuxian.db.MongoRepository;
import com.yanqu.xiuxian.entity.enums.SystemId;
import com.yanqu.xiuxian.gameserver.config.GameServerConfigMgr;
import com.yanqu.xiuxian.gameserver.gameplayer.GamePlayer;
import com.yanqu.xiuxian.gameserver.gameplayer.module.elementalbonds.ElementalBondsModule;
import com.yanqu.xiuxian.gameserver.gameplayer.module.elementalbonds.entity.ElementalBondsPlayerData;
import com.yanqu.xiuxian.gameserver.gameplayer.module.mail.ServerMailMgr;
import com.yanqu.xiuxian.gameserver.gameplayer.module.mail.entity.ServerMail;
import com.yanqu.xiuxian.gameserver.gameplayer.module.mail.enums.MailType;
import com.yanqu.xiuxian.gameserver.manger.elementalbonds.entity.*;
import com.yanqu.xiuxian.gameserver.manger.elementalbonds.pb.ElementalBondsPb;
import com.yanqu.xiuxian.gameserver.manger.player.GamePlayerMgr;
import com.yanqu.xiuxian.gameserver.net.connect.AgentLinkControl;
import com.yanqu.xiuxian.gameserver.timer.GeneralAgentTimerMgr;
import com.yanqu.xiuxian.message.YanQuMessage;
import com.yanqu.xiuxian.pb.activity.ActivityBase;
import com.yanqu.xiuxian.pb.cross.system.CrossElementalBonds;
import com.yanqu.xiuxian.pb.elementalbonds.ElementalBonds;
import com.yanqu.xiuxian.pb.player.Rank;
import com.yanqu.xiuxian.server.TempMgr;
import com.yanqu.xiuxian.server.protocol.GameErrorCode;
import com.yanqu.xiuxian.utils.TimeUtils;
import com.yanqu.xiuxian.utils.YanQuMessageUtils;
import com.yanqu.xiuxian.utils.date.DateHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.atomic.AtomicBoolean;

public class ElementalBondsMgr extends TempMgr {

    private final Logger logger = LoggerFactory.getLogger(ElementalBondsMgr.class);
    public final int BATTLE_PASS_CONDITION_TYPE = 1;  // 战令任务类型

    /**
     * 添加和移出 赛区和参赛成员专用的锁
     */
    private final Object seasonLock = new Object();
    // 游戏时的ping
    public final Map<Long, ElementalBondsPingData> pingMap = new ConcurrentHashMap<>();

    // 勋章数据（其他玩家可以查看）
    public long badgeClearTime = TimeUtils.currentTimeMillis();
    public final ConcurrentHashMap<Long, ElementBondsBadgeResultData> badgeResultMap = new ConcurrentHashMap<>();
    public int seasonId;
    // 今日玩法（跨域同步下来）
    private List<Integer> sceneList = new ArrayList<>();
    private long syncSceneTime = 0;
    // 赛季排名     赛季id，榜单类型，rank
    public Map<Integer, Map<Integer, ElementalBondsHistoryRank>> historyRankMap = new ConcurrentHashMap<>();
    // 最后一次对局结果
    public final ConcurrentHashMap<Long, ElementalBondsLastResultData> lastResultMap = new ConcurrentHashMap<>();
    //赛季配置 k:赛季id v:赛季时间配置
    public ConcurrentHashMap<Integer, ElementalBondsSeasonConfig> seasonConfigMap = new ConcurrentHashMap<>();
    private int serverRound;
    ElementalBondsSeasonConfig seasonConfig;

    // 匹配屏蔽开关
    private final AtomicBoolean matchShield = new AtomicBoolean(false);

    private ElementalBondsMgr() {
    }

    private static final class ElementalBondsMgrHolder {
        static final ElementalBondsMgr elementalBondsMgr = new ElementalBondsMgr();
    }

    public static ElementalBondsMgr getInstance() {
        return ElementalBondsMgrHolder.elementalBondsMgr;
    }

    @Override
    public boolean reload() throws Exception {
        reloadSeasonConfig();
        //加载勋章
        List<ElementBondsBadgeResultData> bondsBadgeResultDataList = MongoRepository.selectList(new Query(), ElementBondsBadgeResultData.class);
        for (ElementBondsBadgeResultData bondsBadgeResultData : bondsBadgeResultDataList) {
            badgeResultMap.put(bondsBadgeResultData.getPlayerId(), bondsBadgeResultData);
        }

        //历史排行榜
        List<ElementalBondsHistoryRank> historyRanks = MongoRepository.selectList(new Query(Criteria.where("seasonId").is(seasonId)), ElementalBondsHistoryRank.class);
        Map<Integer, Map<Integer, ElementalBondsHistoryRank>> historyRankMap = new ConcurrentHashMap<>();
        for (ElementalBondsHistoryRank historyRank : historyRanks) { //目前只有一个榜单
            Map<Integer, ElementalBondsHistoryRank> rankMap = historyRankMap.computeIfAbsent(historyRank.getSeasonId(), k -> new HashMap<>());
            rankMap.put(historyRank.getRankType(), historyRank);
        }
        this.historyRankMap = historyRankMap;

        return true;
    }

    private void reloadSeasonConfig() {
        //加载赛季配置
        Map<Integer, List<Long>> elementalBondsTime = BusinessServerParamConfigParam.ELEMENTAL_BONDS_TIME;

        if (elementalBondsTime == null || elementalBondsTime.isEmpty()) {
            throw new RuntimeException("elementalBondsTime is null");
        }
        Map<Integer, Integer> elementalBondsPeriodTime = ElementalBondsParam.getInstance().getPeriodTimeMap();
        if (elementalBondsPeriodTime == null || elementalBondsPeriodTime.isEmpty()) {
            throw new RuntimeException("elementalBondsPeriodTime is null");
        }
        long showDuration = elementalBondsPeriodTime.get(1) * TimeUtils.MINUTE_MILLIS;
        long rewardDuration = elementalBondsPeriodTime.get(2) * TimeUtils.MINUTE_MILLIS;
        for (Map.Entry<Integer, List<Long>> entry : elementalBondsTime.entrySet()) {
            int tmpSeasonId = entry.getKey();
            List<Long> timeList = entry.getValue();
            long beginShowTime = timeList.get(0);
            long endShowTime = timeList.get(1);
            ElementalBondsSeasonConfig seasonConfig = new ElementalBondsSeasonConfig();
            seasonConfig.setSeasonId(tmpSeasonId);
            seasonConfig.setBeginShowTime(beginShowTime);
            seasonConfig.setEndShowTime(endShowTime);
            seasonConfig.setPublicityEndTime(beginShowTime + showDuration);
            seasonConfig.setRewardBeginTime(endShowTime - rewardDuration);
            seasonConfigMap.put(tmpSeasonId, seasonConfig);
        }
        seasonId = calculateSeasonId();
    }

    public int calculateSeasonId() {
        //计算当前赛季
        int seasonId = 0;
        long nowTime = TimeUtils.currentTimeMillis();
        long preSeasonEndTime = 0;
        int preSeasonId = 0;
        Map<Integer, List<Long>> elementalBondsTime = BusinessServerParamConfigParam.ELEMENTAL_BONDS_TIME;
        for (Map.Entry<Integer, List<Long>> entry : elementalBondsTime.entrySet()) {
            long seasonBeginTime = entry.getValue().get(0);
            long seasonEndTime = entry.getValue().get(1);
            if (seasonBeginTime <= nowTime && seasonEndTime >= nowTime) {
                seasonId = entry.getKey();
            }
            if (seasonEndTime < nowTime && (seasonEndTime < preSeasonEndTime || preSeasonEndTime == 0)) {
                preSeasonEndTime = seasonEndTime;
                preSeasonId = entry.getKey();
            }
        }
        if (seasonId == 0) {
            seasonId = preSeasonId;
        }
        return seasonId;
    }

    @Override
    public boolean save(boolean forceSave) {
        if (!badgeResultMap.isEmpty()) {
            for (ElementBondsBadgeResultData bondsBadgeResultData : badgeResultMap.values()) {
                MongoRepository.save(bondsBadgeResultData);
            }
        }
        if (!historyRankMap.isEmpty()) {
            for (Map<Integer, ElementalBondsHistoryRank> rankMap : historyRankMap.values())
                for (ElementalBondsHistoryRank historyRank : rankMap.values())
                    MongoRepository.save(historyRank);
        }
        // 半夜四点移除旧数据
        if (DateHelper.getHours() == 4) {

            for (ElementalBondsLastResultData data : lastResultMap.values()) {
                if (GamePlayerMgr.getOnlinePlayer(data.getPlayerId()) == null && !data.isInsert()) {
                    lastResultMap.remove(data.getPlayerId());
                }
            }

            if (TimeUtils.currentTimeMillis() - badgeClearTime > DateHelper.HOUR_MILLIONS) {
                synchronized (badgeResultMap) {
                    badgeClearTime = TimeUtils.currentTimeMillis();
                    badgeResultMap.clear();
                }
            }

        }

        return true;
    }

    @Override
    public boolean stop() {
        return false;
    }

    public ElementalBondsUseKey getUserKey(long userId) {
        long serverId = GameServerConfigMgr.getInstance().getServerId();
        int channelId = GameServerConfigMgr.getInstance().getChannelId();

        ElementalBondsUseKey userKey = new ElementalBondsUseKey();
        userKey.setPlayerId(userId);
        userKey.setServerId(serverId);
        userKey.setChannelId(channelId);
        return userKey;
    }

    //心跳
    public boolean ping(long playerId) {
        synchronized (pingMap) {
            ElementalBondsPingData data = pingMap.get(playerId);
            if (data == null) {
                return false;
            }

            // 掉线被检测后2秒内重连，每次都上传重连，避免跟掉线顺序乱掉
            if (data.isDisconnect()) {
                long disconnectTime = ElementalBondsParam.getInstance().getDisconnectTime(data.getDissconnectCount());
                long costTime = TimeUtils.currentTimeMillis() - data.getPingTime();
                if (costTime - disconnectTime < 2000) {
                    // 上传掉线恢复
                    sendPlayerStatus(playerId, 2);
                    return true;
                }
            }

            // 掉线重连加个日志
            if (data.isDisconnect()) {
                // 日志

            }

            data.setPingTime(TimeUtils.currentTimeMillis());

            if (data.isDisconnect()) {
                // 断线重连
                data.setDisconnect(false);

                // 上传掉线恢复
                sendPlayerStatus(playerId, 2);
            }
            return true;
        }
    }

    public void removePing(long userId) {
        synchronized (pingMap) {
            pingMap.remove(userId);
        }
    }

    public void beginPing(long userId) {
        synchronized (pingMap) {
            ElementalBondsPingData data = pingMap.get(userId);
            if (data == null) {
                data = new ElementalBondsPingData();
                data.setUserId(userId);
                pingMap.put(userId, data);
            }
            data.setPingTime(TimeUtils.currentTimeMillis());
            data.setDisconnect(false);
        }
    }

    public void checkPingByTimer() {

        if (seasonId == 0) {
            return;
        }


        synchronized (pingMap) {
            for (Map.Entry<Long, ElementalBondsPingData> entry : pingMap.entrySet()) {
                long playerId = entry.getKey();
                ElementalBondsPingData pingData = entry.getValue();
                // 超过该时间未ping就设置为掉线
                long disconnectTime = ElementalBondsParam.getInstance().getDisconnectTime(pingData.getDissconnectCount()) * TimeUtils.SECONDS_MILLIS;
                // 掉线了
                if (!pingData.isDisconnect() && TimeUtils.currentTimeMillis() - pingData.getPingTime() > disconnectTime) {
                    pingData.setDisconnect(true);
                    pingData.setDissconnectCount(pingData.getDissconnectCount() + 1);
                    // 上传掉线状态
                    sendPlayerStatus(playerId, 1);
                    // 日志
                }

                // 很久没ping的移除掉
                if (TimeUtils.currentTimeMillis() - pingData.getPingTime() > DateHelper.DAY_MILLIONS) {
                    removePing(playerId);
                    // 日志
                }
            }
        }
    }

    public void reloadConfig() {
        reloadSeasonConfig();
    }

    //添加
    public void addTempHistoryValue(Map<Integer, Long> typeValueMap, ElementalBondsHonorMomentType type, long addValue) {
        Long oldValue = typeValueMap.getOrDefault(type.getType(), 0L);
        typeValueMap.put(type.getType(), oldValue + addValue);
    }

    public void updateTodayScene(List<Integer> list) {
        syncSceneTime = TimeUtils.currentTimeMillis();
        sceneList = list;

        // 同步在线玩家
        if (seasonId != 0) {
            for (GamePlayer player : GamePlayerMgr.getOnlinePlayers()) {
                ElementalBondsModule module = player.getModule(ElementalBondsModule.class);
                ElementalBondsPlayerData userData = module.getPlayerData();
                if (userData != null) {
                    module.syncPlayerData();
                }
            }
        }
    }

    private void sendPlayerStatus(long playerId, int type) {
        CrossElementalBonds.ChannelElementalBondsStatusReqMsg.Builder builder = CrossElementalBonds.ChannelElementalBondsStatusReqMsg.newBuilder();
        builder.setUserKey(ElementalBondsPb.parseElementalBondsUserKeyMsg(getUserKey(playerId)));
        builder.setType(type);
        YanQuMessage msg = YanQuMessageUtils.buildYanQuSystemMessage(SystemId.ElementalBonds, CrossElementalBonds.CrossElementalBondsPb.GameToCross_ElementalBonds_STATUS_VALUE, playerId);
        msg.setBytes(builder.build().toByteArray());
        AgentLinkControl.routeCrossServer(msg);
    }

    public int getSeasonId() {
        return seasonId;
    }

    public List<Integer> getSceneList() {
        return sceneList;
    }

    public List<Integer> removeZeroSkillId(List<Integer> skillIdList) {
        List<Integer> list = new ArrayList<>();
        for (int skillId : skillIdList) {
            if (skillId > 0) {
                list.add(skillId);
            }
        }
        return list;
    }

    /**
     * @param skillIdList 检查下这个参数，不能是协议里的list直接拿过来，不然会报错
     */
    public int checkChooseSkill(List<Integer> skillIdList, ConcurrentSkipListSet<Integer> unlockedSkillId) {
        if (seasonId == 0) {
            return GameErrorCode.E_ELEMENTAL_BONDS_SEASON_NO_EXIST;
        }

        // 技能数量不对，提示没技能
        if (skillIdList.size() != 2) {
            return GameErrorCode.E_ELEMENTAL_BONDS_NOT_SELECT_SKILL;
        }
        // 技能重复
        if (Objects.equals(skillIdList.get(0), skillIdList.get(1))) {
            return GameErrorCode.E_ELEMENTAL_BONDS_SKILL_SELECT_REPEAT;
        }
        // 存在 && 开启
        Map<Integer, ElementalBondsSkillConfig> skillConfigMap = ElementalBondsConfigMgr.getInstance().getSkillConfigMap();
        for (int skillId : skillIdList) {
            ElementalBondsSkillConfig skillConfig = skillConfigMap.get(skillId);
            if (skillConfig == null) {
                return GameErrorCode.E_ELEMENTAL_BONDS_SKILL_CONFIG_NO_EXIST;
            }
            if (!unlockedSkillId.contains(skillId)) {
                return GameErrorCode.E_ELEMENTAL_BONDS_SKILL_NO_UNLOCK;
            }
        }
        return 0;
    }

    public void addLastResultData(long playerId, ElementalBonds.ElementalBondsGameOverMsg msg, boolean handle) {
        byte[] bytes = msg.toByteArray();
        String msgData = Base64.getEncoder().encodeToString(bytes);

        ElementalBondsLastResultData data = getLastResultData(playerId);
        // 修改数据
        synchronized (data) {
            data.setSeasonId(seasonId);
            data.setMsgData(msgData);
            data.setHandled(handle);
            data.setRead(false);
            data.setEndTime(TimeUtils.currentTimeMillis());
        }
    }

    public ElementalBondsLastResultData getLastResultData(long playerId) {
        synchronized (lastResultMap) {
            ElementalBondsLastResultData data = lastResultMap.get(playerId);
            if (data == null) {
                data = reloadLastResultData(playerId);
                if (data == null) {
                    data = new ElementalBondsLastResultData();
                    data.setPlayerId(playerId);
                    data.setSeasonId(-1);
                    data.setMsgData("");
                    data.setHandled(true);
                    data.setRead(true);
                    data.setEndTime(0);
                    data.setInsert(true);
                    lastResultMap.put(playerId, data);
                }
            }

            return data;
        }
    }

    private ElementalBondsLastResultData reloadLastResultData(long playerId) {
        return MongoRepository.selectOne(new Query(Criteria.where("playerId").is(playerId).andOperator(Criteria.where("seasonId").is(seasonId))), ElementalBondsLastResultData.class);
    }

    public int addElementalBondsBadgeResult(long playerId, ElementalBondsPlayerData playerData, int badgeId, long value, boolean isAdd, int seasonId) {
        ConcurrentHashMap<Integer, Long> seasonScoreMap = playerData == null ? new ConcurrentHashMap<>() : playerData.getSeasonScoreMap();
        int seasonIdNull = ElementalBondsConfigMgr.getInstance().getSeasonIdNull();
        long curScore = seasonId == seasonIdNull ? 0L : seasonScoreMap.getOrDefault(seasonId, 0L);
        ElementBondsBadgeResultData elementBondsBadgeResultData = badgeResultMap.computeIfAbsent(playerId, k -> new ElementBondsBadgeResultData(playerId));
        int completeStatus = 0;
        if (seasonId > 0) {
            elementBondsBadgeResultData.getSeasonBadgeMap().computeIfAbsent(badgeId, k -> new ElementalBondsBadgeData(0, seasonId, curScore));
        } else {
            ElementalBondsBadgeData elementalBondsBadgeData = elementBondsBadgeResultData.getPlayBadgeMap().computeIfAbsent(badgeId, k -> new ElementalBondsBadgeData(badgeId, seasonId, 0));
            long oldValue = elementalBondsBadgeData.getScore();
            ElementalBondsAchieveConfig achieveConfig = ElementalBondsConfigMgr.getInstance().getMedalConfigMap().get(badgeId);

            if (isAdd) {
                elementalBondsBadgeData.setScore(elementalBondsBadgeData.getScore() + value);
            } else {
                elementalBondsBadgeData.setScore(value);
            }
            if (achieveConfig != null) {
                completeStatus = getCompleteStatus(value, achieveConfig, oldValue, completeStatus);
                if (completeStatus > 0) {
                    elementalBondsBadgeData.setNew(true);
                }
                if (oldValue == 0) {
                    elementalBondsBadgeData.setNew(true);
                    completeStatus += 1;
                }
            }
        }
        elementBondsBadgeResultData.setChangeState();
        return completeStatus;
    }

    private int getCompleteStatus(long value, ElementalBondsAchieveConfig achieveConfig, long oldValue, int completeType) {
        int oldLv = 0;
        int maxLv = achieveConfig.getParam().size();
        for (Integer condition : achieveConfig.getParam()) {
            if (oldValue > condition) {
                oldLv++;
            } else {
                break;
            }
        }
        int newLv = oldLv;
        for (int i = oldLv; i < maxLv; i++) {
            Integer condition = achieveConfig.getParam().get(oldLv);
            if (value >= condition) {
                newLv++;
            }
        }
        if (newLv > oldLv) {
            completeType += 1;
        }
        return completeType;
    }

    public ElementBondsBadgeResultData refreshWasheTmpBadgeResult(long playerId, ElementalBondsPlayerData playerData) {

        Map<Integer, Long> seasonScoreMap = playerData == null ? new HashMap<>() : playerData.getSeasonScoreMap();
        long curScore = seasonId == ElementalBondsConfigMgr.getInstance().getSeasonIdNull() ? 0L : seasonScoreMap.getOrDefault(seasonId, 0L);

        ElementBondsBadgeResultData resultData = badgeResultMap.computeIfAbsent(playerId, k -> new ElementBondsBadgeResultData());
        // 拿各个赛季勋章
        List<ElementalBondsBadgeData> seasonBadgeList = new ArrayList<>();
        for (ElementalBondsBadgeData badge : resultData.getSeasonBadgeMap().values()) {
            ElementalBondsBadgeData tmpBadge = new ElementalBondsBadgeData(
                    0,
                    badge.getSeasonId(),
                    seasonScoreMap.getOrDefault(badge.getSeasonId(), 0L)
            );
            seasonBadgeList.add(tmpBadge);
        }

        // 最高
        ElementalBondsBadgeData top = getTopBadgeData(seasonScoreMap, seasonBadgeList);
        //resultData.setCur(cur);
        resultData.setTop(top);

        return resultData;
    }

    private ElementalBondsBadgeData getTopBadgeData(Map<Integer, Long> seasonScoreMap, List<ElementalBondsBadgeData> seasonBadgeList) {
        int topSeason = 0;
        long topScore = 0;
        for (Map.Entry<Integer, Long> entry : seasonScoreMap.entrySet()) {
            int tmpSeason = entry.getKey();
            long tmpScore = entry.getValue();
            if (tmpSeason <= 0 || tmpSeason == seasonId) { // 历史最高不要当前赛季
                continue;
            }
            if (tmpScore > topScore ||
                    tmpScore == topScore && tmpSeason > topSeason) { // 取最高分 || 分数相同取新赛季
                topSeason = tmpSeason;
                topScore = tmpScore;
            }
        }

        ElementalBondsBadgeData top = null;
        if (topSeason > 0) {
            for (ElementalBondsBadgeData tmpBadge : seasonBadgeList) {
                if (tmpBadge.getSeasonId() == topSeason) {
                    if (top == null) {
                        top = tmpBadge;
                    }
                }
            }
        }
        if (top == null) {
            top = new ElementalBondsBadgeData(0, topSeason, topScore);
        }
        return top;
    }

    public ElementalBondsBadgeData getBadgeData(long playerId, int badgeId) {
        ElementBondsBadgeResultData elementBondsBadgeResultData = badgeResultMap.computeIfAbsent(playerId, k -> new ElementBondsBadgeResultData());
        return elementBondsBadgeResultData.getSeasonBadgeMap().get(badgeId);
    }
    public void addHistoryRank(int seasonId, int rankType, ConcurrentHashMap<Long, Integer> map, ElementalBondsRankData topRank) {
        synchronized (historyRankMap) {
            historyRankMap.computeIfAbsent(seasonId, k -> new ConcurrentHashMap<>());
            ElementalBondsHistoryRank historyRank = historyRankMap.get(seasonId).get(rankType);
            if (historyRank == null) {
                historyRank = new ElementalBondsHistoryRank();
                historyRank.setSeasonId(seasonId);
                historyRank.setUserRankMap(map);
                historyRank.setTopRank(topRank);
                historyRank.setRankType(rankType);
                historyRankMap.get(seasonId).put(rankType, historyRank);
            } else {
                historyRank.setUserRankMap(map);
                historyRank.setTopRank(topRank);
            }
        }
    }

    public int getHistoryRank(int seasonId, int rankType, long userId) {
        Map<Integer, ElementalBondsHistoryRank> rankMap = historyRankMap.get(seasonId);
        if (rankMap == null) {
            return -1;
        }
        ElementalBondsHistoryRank historyRank = rankMap.get(rankType);
        if (historyRank == null) {
            return -1;
        }

        return historyRank.getUserRankMap().getOrDefault(userId, -1);
    }

    public Map<Integer, Map<Integer, ElementalBondsHistoryRank>> getHistoryRankMap() {
        return historyRankMap;
    }

    public void tryAutoSendBattlePassReward() {
        if (seasonId == 0) {
            return;
        }

        // 【找刚过期的赛季配置】
        ElementalBondsSeasonConfig curConfig = null; //万一没有间隔 重新算一下
        long now = TimeUtils.currentTimeMillis();
        curConfig = getElementalBondsSeasonConfig(now);
        if (curConfig == null || curConfig.getSeasonId() <= 0) {
            return;
        }
        logger.info("开始补发夺魁未领取的任务奖励, seasonId={}", seasonId);

        //TODO:待补充
    }

    public ElementalBondsSeasonConfig getElementalBondsSeasonConfig(long now) {
        for (ElementalBondsSeasonConfig seasonConfig : seasonConfigMap.values()) {
            if (now >= seasonConfig.getBeginShowTime() && now < seasonConfig.getEndShowTime()) {
                return seasonConfig;
            }
        }
        return null;
    }

    public boolean seasonInTime() {
        seasonId = calculateSeasonId();
        if (seasonId == 0) {
            return false;
        }
        return seasonConfigMap.get(seasonId).getEndShowTime() > TimeUtils.currentTimeMillis();
    }

    public ElementalBondsSeasonConfig getSeasonConfig(int seasonId) {
        return seasonConfigMap.get(seasonId);
    }

    public ElementalBondsSeasonConfig getSeasonConfig() {
        return seasonConfigMap.get(seasonId);
    }

    public ElementBondsBadgeResultData getBadgeResultData(long playerId) {
        return badgeResultMap.get(playerId);
    }

    public boolean inRechargeTokenTime() {
        if (seasonId == 0) {
            return false;
        }
        ElementalBondsSeasonConfig seasonConfig = getSeasonConfig(seasonId);
        if (seasonConfig == null || seasonConfig.getSeasonId() <= 0) {
            return false;
        }

        long now = TimeUtils.currentTimeMillis();
        return now >= seasonConfig.getBeginShowTime() && now <= seasonConfig.getEndShowTime() - 10 * TimeUtils.MINUTE_MILLIS;
    }

    public void checkTodayScene() {
        if (seasonId != 0) {
            // 10分钟主动请求一次
            if (TimeUtils.isSameDay(syncSceneTime, TimeUtils.currentTimeMillis())) return;
            if (TimeUtils.currentTimeMillis() > syncSceneTime + DateHelper.MINUTE_MILLIONS * 10 || !TimeUtils.isSameDay(syncSceneTime, TimeUtils.currentTimeMillis())) {
                ElementalBondsUseKey userKey = getUserKey(0);
                CrossElementalBonds.ChannelElementalBondsGetDaySceneReqMsg.Builder builder = CrossElementalBonds.ChannelElementalBondsGetDaySceneReqMsg.newBuilder();
                builder.setUserKey(ElementalBondsPb.parseElementalBondsUserKeyMsg(userKey));
                YanQuMessage msg = YanQuMessageUtils.buildYanQuSystemMessage(SystemId.ElementalBonds, CrossElementalBonds.CrossElementalBondsPb.GameToCross_ElementalBonds_GET_GET_DAY_SCENE_VALUE, 0);
                msg.setBytes(builder.build().toByteArray());
                AgentLinkControl.routeCrossServer(msg);

            }
        }
    }

    public int getServerRound() {
        return serverRound;
    }

    public void setServerRound(int serverRound) {
        this.serverRound = serverRound;
    }

    public void getRankList(long playerId, int rankType) {
        CrossElementalBonds.CrossElementalBondsGetRankRecordReqMsg.Builder builder = CrossElementalBonds.CrossElementalBondsGetRankRecordReqMsg.newBuilder();
        builder.setSeasonId(seasonId);
        builder.setRankType(rankType);
        builder.setUserKey(ElementalBondsPb.parseElementalBondsUserKeyMsg(getUserKey(playerId)));
        YanQuMessage message = YanQuMessageUtils.buildYanQuSystemMessage(SystemId.ElementalBonds, CrossElementalBonds.CrossElementalBondsPb.GameToCross_ElementalBonds_GET_RANK_LIST_VALUE, playerId, builder);
        AgentLinkControl.routeCrossServer(message);
    }

    //获取排行榜奖励
    public void getRankAward(long playerId, int type) {
        Rank.GetRankAwardReq.Builder builder = Rank.GetRankAwardReq.newBuilder();
        builder.setRankType(type);
        YanQuMessage message = YanQuMessageUtils.buildYanQuSystemMessage(SystemId.ElementalBonds, CrossElementalBonds.CrossElementalBondsPb.GameToCross_ElementalBonds_GET_RANK_REWARD_VALUE, playerId, builder);
        message.setPlayerId(playerId);
        AgentLinkControl.routeCrossServer(message);
    }

    //获取排行榜状态
    public void getRankState(long playerId, ActivityBase.ReqGetActivityRankState ctsMsg) {
        ActivityBase.ReqGetActivityRankState.Builder crossBuilder = ActivityBase.ReqGetActivityRankState.newBuilder();
        crossBuilder.setRankType(ctsMsg.getRankType());
        crossBuilder.setSysTemId(SystemId.ElementalBonds.getValue());
        YanQuMessage msg = YanQuMessageUtils.buildYanQuSystemMessage(SystemId.ElementalBonds, CrossElementalBonds.CrossElementalBondsPb.GameToCross_ElementalBonds_GET_RANK_STATE_VALUE, playerId, crossBuilder);
        AgentLinkControl.routeCrossServer(msg);
    }

    // 活动结束 补发赛季任务未领取的奖励
    public void sendTaskReward(long endShowTime) {
        GeneralAgentTimerMgr.getTimerExecutorService().submit(() ->
                ElementalBondsTaskAward.reissueAward(endShowTime));
    }

    public boolean canMatch() {
        //赛季结束前15分钟不能匹配
        return TimeUtils.currentTimeMillis() < getSeasonConfig().getEndShowTime() - TimeUtils.MINUTE_MILLIS * 15;
    }

    public void checkMatchShield() {
        if (matchShield.get()) {
            return;
        }
        matchShield.set(true);
        sendMatchShieldMail();
        syncMatchShield();
    }

    public void sendMatchShieldMail() {
        long serverId = GameServerConfigMgr.getInstance().getServerId();
        logger.info("[sendMatchShieldMail start] : [serverId : {}]", serverId);
        String mailTitle = "ELEMENTAL_BONDS_MAINTENANCE_TITLE";
        String mailContent = "ELEMENTAL_BONDS_MAINTENANCE_CONTENT";
        ServerMail serverMail = ServerMailMgr.getInstance().buildServerMail(MailType.MARKETING.getValue(), mailTitle, mailContent, "", "", "0");
        ServerMailMgr.getInstance().addServerMail(serverMail);
        logger.info("[sendMatchShieldMail end] : [serverId : {}]", serverId);
    }

    public void syncMatchShield() {
        GamePlayerMgr.getOnlinePlayers().forEach(gamePlayer -> {
            ServerMailMgr.getInstance().playerGetServerMail(gamePlayer);
            ElementalBondsModule elementalBondsModule = gamePlayer.getModule(ElementalBondsModule.class);
            elementalBondsModule.syncMatchState(matchShield.get());
        });
    }

    public boolean matchShield() {
        return matchShield.get();
    }

}
